﻿using Eps.Ai.Common;
using InfonavaEye.components;
using InfonavaEye.handler;
using InfonavaEye.util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TUCAMAPI;

namespace InfonavaEye.Handler
{
    public class CameraHandler
    {
        TUCAM_INIT m_itApi;                 // SDK initialize environment object

        int m_pid;                          // The current used camera PID  s
        protected int m_indexCam;                     // The current used camera index
        protected List<TUCAM_OPEN> m_opCamList;       // The list of opened cameras object   
        //List<TUCAM_DRAW_INIT> m_itDrawList; // The list of drawing object

        UInt64 m_drawingFramesCnt;          // The count of drawing frames
        TimeSpan m_startTime;               // The start time count
        float m_fps;                        // The current frame speed

        int m_clientWinWidth;               // The current client window width
        int m_clientWinHeight;              // The current client window height
        TUCAM_DRAW m_drawing;               // The drawing object
        TUCAM_FRAME m_frame;                // The frame which get from SDK
        Thread m_waitingThread;             // The waiting frame thread

        TUCAM_TRIGGER_ATTR m_triggerAttr;   // The trigger parameter attribute

        bool m_isWaiting;                   // Is waiting for the image frame
        bool m_isSaving;                    // Is saving the image
        bool m_isRecording;                 // Is recording the video
        bool m_isRoi;                       // Is on ROI mode
        bool m_isTrigger;                   // Is trigger mode

        int m_totalFrames;                  // The saved image total frames
        int m_savedFormat;                  // The format of saved image 
        int m_savedFormatCnt;               // The count of saved image format
        int m_captureTimes;                 // The capture times
        int m_savedFramesCnt;               // The count of saved frames
        int m_savedSucceedCnt;              // The count of image succeed

        string m_filePath;                  // The file path where to save image file and video file
        string m_imageName;                 // The saved image name

        System.Timers.Timer m_aeTimer;              // The auto exposure timer
        System.Timers.Timer m_onceAeTimer;          // The once auto exposure timer
        System.Timers.Timer m_autoLeftLevelsTimer;  // The auto left levels timer
        System.Timers.Timer m_autoRightLevelsTimer; // The auto right levels timer
        System.Timers.Timer m_awbTimer;             // The auto white balance timer
        System.Timers.Timer m_onceWbTimer;          // The once white balance timer

        // public delegate void FinishedCaptureInvoke(int savedSucceedCnt);

        public delegate void CaptureImageDelegate(string imagePath);
        public event CaptureImageDelegate captureImageDelegate;

        public event Action initCompleteDelegate;
        public event Action openCompleteDelegate;

        private PictureBox drawingBox;
        //private Form form;

        //心跳监测
        private bool heartBeatEnabled = false;
        System.Timers.Timer heartBeatTimer = null;
        public event Action<bool> heartBeatDelegate;

        private bool inited = false;//是否已经初始化

        private static readonly CameraHandler instance = new CameraHandler();

        static CameraHandler() { }
        private CameraHandler() { }
        public static CameraHandler Instance
        {
            get
            {
                return instance;
            }
        }

        /* public CameraHandler(Form form,PictureBox drawingBox) {
             this.drawingBox = drawingBox;
             this.form = form;
         }*/

        /// <summary>
        /// 文件批次
        /// （每天每个文件批次创建一个新的文件夹：比如换了下一个钉盒，清除了数据，就需要增加这个批次）
        /// </summary>
        private int currentFileBatchNum = 1;

        private string baseDir;
        public static string CurrentBatchDir;
        private SoundPlayer soundPlayer;

        /// <summary>
        /// 抓拍状态
        /// </summary>
        public static bool captureing = false;

        private bool opened = false;

        public void open(bool force = false)
        {
            if (opened && force)
            {
                Console.WriteLine("强制重新打开相机");
                this.stop();
            }
            else if (opened)
            {
                if (openCompleteDelegate != null)
                {
                    openCompleteDelegate.Invoke();
                }
                return;
            }

            this.createBaseDir();
            InitTimer();
            m_opCamList = new List<TUCAM_OPEN>();
            //m_itDrawList = new List<TUCAM_DRAW_INIT>();

            try
            {
                if (TUCAMRET.TUCAMRET_NO_CAMERA == InitApi())
                {
                    MessageBox.Show("无法连接相机", "提示");
                    return;
                }

                if (TUCAMRET.TUCAMRET_FAILOPEN_CAMERA == OpenAllConnectedCameras())
                {
                    MessageBox.Show("无法打开相机", "提示");
                    try
                    {
                        TUCamAPI.TUCAM_Api_Uninit();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("TUCAM_Api_Uninit发生异常：{0}，{1}", ex.Message, ex.StackTrace);
                    }
                    return;
                }
                opened = true;
                if (openCompleteDelegate != null)
                {
                    openCompleteDelegate.Invoke();
                }
                Console.WriteLine("打开相机成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("打开相机报错：{0}", ex.Message));
                return;
            }
        }

        public void play(PictureBox box)
        {
            if (!opened)
            {
                AutoCloseMessageBox.Show("还未连接相机");
                return;
            }
            this.drawingBox = box;
            if (m_isWaiting)
            {
                StopWaitForFrame(m_opCamList[m_indexCam]);
            }

            if (this.inited)
            {
                UnInitAllOpenedCamerasDrawing();
            }

            InitAllOpenedCamerasDrawing();

            // Set current selected camera
            m_indexCam = 0;
            m_isSaving = false;
            m_isRecording = false;
            m_clientWinWidth = 0;
            m_clientWinHeight = 0;

            InitImageCaptureValue();
            InitControlRange(m_opCamList[m_indexCam]);
            //form.PerformLayout();
            if (initCompleteDelegate != null)
            {
                initCompleteDelegate.Invoke();
            }
            Console.WriteLine("相机初始化完成");
            //          splitContainer1.Panel1.PerformLayout();
            //自动打开录制
            //buttonLive_Click(null, null);
            //曝光时间
            //numericUpDownMs.Value = 15;
            //buttonExpOK_Click(null, null);
            if (m_opCamList.Count > 0)
            {
                StartWaitForFrame(m_opCamList[m_indexCam]);
                drawingBox.Refresh();
            }
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void pause()
        {
            if (m_isWaiting)
            {
                StopWaitForFrame(m_opCamList[m_indexCam]);
            }
        }

        public void InitDir()
        {
            //当前目录
            baseDir = FileHelper.getBaseDir();
            m_filePath = baseDir + "\\Image";

            //得到正确的currentFileBatchNum
            //（每天每个文件批次创建一个新的文件夹：比如换了下一个钉盒，清除了数据，就需要增加这个批次）
            string dir = m_filePath + "\\" + DateTime.Now.ToString("yyyy-MM-dd");
            string batchDir = dir + '\\' + currentFileBatchNum;
            if (!Directory.Exists(batchDir))
            {
                Directory.CreateDirectory(batchDir);
            }
            else
            {
                currentFileBatchNum = Directory.EnumerateFileSystemEntries(dir).Max(p =>
                {
                    var startIndex = p.LastIndexOf("\\");
                    //Console.WriteLine(p.Substring(startIndex + 1, p.Length - startIndex - 1));
                    return int.Parse(p.Substring(startIndex + 1, p.Length - startIndex - 1));
                });

                //空文件夹将继续使用，非空就创建新的
                if (Directory.GetFiles(dir + '\\' + currentFileBatchNum).Length > 0)
                {
                    currentFileBatchNum++;
                    Directory.CreateDirectory(dir + '\\' + currentFileBatchNum);
                }
            }
        }
        //创建图片父目录
        public void createBaseDir() {
            //当前目录
            baseDir = FileHelper.getBaseDir();
            m_filePath = baseDir + "\\Image";
            if (!Directory.Exists(m_filePath))
            {
                Directory.CreateDirectory(m_filePath);
            }
        }

        public void createImageDir()
        {
            //当前目录
            baseDir = FileHelper.getBaseDir();
            m_filePath = baseDir + "\\Image";
            string dir = m_filePath + "\\" + DateTime.Now.ToString("yyyy-MM-dd");
            string batchDir = dir + '\\' + DateTime.Now.ToString("HHmmss");
            CurrentBatchDir = batchDir;
            if (!Directory.Exists(batchDir))
            {
                Directory.CreateDirectory(batchDir);
            }
        }

        public void stop()
        {
            try
            {
                if (m_isWaiting)
                {
                    StopWaitForFrame(m_opCamList[m_indexCam]);
                }
                UnInitAllOpenedCamerasDrawing();
                CloseAllOpenedCameras();
                UnInitApi();
                opened = false;

                if (soundPlayer != null)
                {
                    soundPlayer.Stop();
                    soundPlayer.Dispose();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("关闭相机发生异常：", ex.Message, ex.StackTrace);
            }
        }

        private void InitTimer()
        {
            heartBeatTimer = new System.Timers.Timer(Config.CAMERA_HEARTBEAT_INTEVAL);
            heartBeatTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerHeartBeat);
            heartBeatTimer.AutoReset = true;
            heartBeatTimer.Enabled = false;
            heartBeatTimer.Stop();
        }

        private void InitImageCaptureValue()
        {
            int totalFrames = 1;
            /* textBoxPath.Text = m_filePath;
             textBoxImageName.Text = "TS";
             textBoxTotalFrames.Text = totalFrames.ToString();

             checkBoxTiff.Checked = true;
             checkBoxRaw.Checked = false;
             checkBoxJpg.Checked = false;
             checkBoxPng.Checked = false;
             checkBoxBmp.Checked = false;*/

            m_savedFormatCnt = 1;
            m_savedFormat = (int)(TUIMG_FORMATS.TUFMT_JPG);

            m_captureTimes = 0;
            m_savedFramesCnt = 1;
            m_savedSucceedCnt = 0;
        }

        private TUCAMRET InitApi()
        {
            /* Get the current directory */
            IntPtr strPath = Marshal.StringToHGlobalAnsi(System.Environment.CurrentDirectory);

            m_filePath = Marshal.PtrToStringAnsi(strPath) + "\\Image";

            m_itApi.uiCamCount = 0;
            m_itApi.pstrConfigPath = strPath;

            TUCamAPI.TUCAM_Api_Init(ref m_itApi);

            Console.WriteLine("Connect {0} camera", m_itApi.uiCamCount);

            if (0 == m_itApi.uiCamCount)
            {
                return TUCAMRET.TUCAMRET_NO_CAMERA;
            }

            return TUCAMRET.TUCAMRET_SUCCESS;
        }

        private TUCAMRET UnInitApi()
        {
            return TUCamAPI.TUCAM_Api_Uninit();
        }

        public bool isCameraOpening = false;
        private TUCAMRET OpenAllConnectedCameras()
        {
            try
            {
                // Get the camera name
                TUCAM_VALUE_INFO valueInfo;
                valueInfo.nID = (int)TUCAM_IDINFO.TUIDI_CAMERA_MODEL;
                valueInfo.nTextSize = 64;
                valueInfo.nValue = 0;
                valueInfo.pText = IntPtr.Zero;
                m_opCamList.Clear();

                for (uint i = 0; i < m_itApi.uiCamCount; ++i)
                {
                    TUCAM_OPEN opCam;
                    opCam.uiIdxOpen = i;
                    opCam.hIdxTUCam = IntPtr.Zero;
                    isCameraOpening = true;
                    if (TUCAMRET.TUCAMRET_SUCCESS == TUCamAPI.TUCAM_Dev_Open(ref opCam))
                    {
                        isCameraOpening = false;
                        if (TUCAMRET.TUCAMRET_SUCCESS == TUCamAPI.TUCAM_Dev_GetInfo(opCam.hIdxTUCam, ref valueInfo))
                        {
                            //comboBoxName.Items.Add(Marshal.PtrToStringAnsi(valueInfo.pText) /*+ " " + labelValueSn.Text*/);
                        }

                        m_opCamList.Add(opCam);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            if (m_opCamList.Count > 0)
            {
                return TUCAMRET.TUCAMRET_SUCCESS;
            }

            return TUCAMRET.TUCAMRET_FAILOPEN_CAMERA;
        }

        private TUCAMRET CloseAllOpenedCameras()
        {
            for (int i = 0; i < m_opCamList.Count; ++i)
            {
                TUCamAPI.TUCAM_Dev_Close(m_opCamList[i].hIdxTUCam);
            }

            m_opCamList.Clear();

            return TUCAMRET.TUCAMRET_SUCCESS;
        }

        private void InitAllOpenedCamerasDrawing()
        {
            TUCAM_OPEN opCam;
            TUCAM_VALUE_INFO valueInfo;
            TUCAM_DRAW_INIT itDraw;
            itDraw.hWnd = drawingBox.Handle;
            itDraw.nMode = 0;

            valueInfo.nID = (int)TUCAM_IDINFO.TUIDI_CAMERA_CHANNELS;
            valueInfo.nValue = 1;
            valueInfo.nTextSize = 0;
            valueInfo.pText = IntPtr.Zero;

            //m_itDrawList.Clear();

            for (int i = 0; i < m_opCamList.Count; ++i)
            {
                opCam = m_opCamList[i];

                valueInfo.nID = (int)TUCAM_IDINFO.TUIDI_CAMERA_CHANNELS;
                TUCamAPI.TUCAM_Dev_GetInfo(opCam.hIdxTUCam, ref valueInfo);
                itDraw.ucChannels = (byte)valueInfo.nValue;

                valueInfo.nID = (int)TUCAM_IDINFO.TUIDI_CURRENT_WIDTH;
                TUCamAPI.TUCAM_Dev_GetInfo(opCam.hIdxTUCam, ref valueInfo);
                itDraw.nWidth = valueInfo.nValue;

                valueInfo.nID = (int)TUCAM_IDINFO.TUIDI_CURRENT_HEIGHT;
                TUCamAPI.TUCAM_Dev_GetInfo(opCam.hIdxTUCam, ref valueInfo);
                itDraw.nHeight = valueInfo.nValue;

                TUCamAPI.TUCAM_Draw_Init(opCam.hIdxTUCam, itDraw);
                this.inited = true;
                //m_itDrawList.Add(itDraw);
            }
        }

        private void UnInitAllOpenedCamerasDrawing()
        {
            for (int i = 0; i < m_opCamList.Count; ++i)
            {
                TUCamAPI.TUCAM_Draw_Uninit(m_opCamList[i].hIdxTUCam);
            }

            //m_itDrawList.Clear();
        }

        private void WaitForFrameThreadEntity()
        {
            int clientWinWidth = 0;
            int clientWinHeight = 0;

            int drawingWidth = 0;
            int drawingHeight = 0;
            int drawingOffsetX = 0;
            int drawingOffsetY = 0;

            UInt64 intervalTime = 0;
            IntPtr hIdxTUCam = m_opCamList[m_indexCam].hIdxTUCam;

            while (m_isWaiting)
            {
                // Calculate the frame speed
                m_drawingFramesCnt++;
                TimeSpan stopTime = new TimeSpan(DateTime.Now.Ticks);
                intervalTime = (UInt64)m_startTime.Subtract(stopTime).Duration().TotalMilliseconds;

                if (intervalTime > 1000)
                {
                    m_fps = m_drawingFramesCnt * 1000.0f / intervalTime;

                    //UpdateFpsInvok updateFps = new UpdateFpsInvok(UpdateFps);
                    //BeginInvoke(updateFps, new object[] { m_fps.ToString("#0.0 fps") });

                    m_startTime = stopTime;
                    m_drawingFramesCnt = 0;
                }

                m_frame.ucFormatGet = (byte)TUFRM_FORMATS.TUFRM_FMT_USUAl;
                var waitForFrameResult = TUCamAPI.TUCAM_Buf_WaitForFrame(hIdxTUCam, ref m_frame);
                if (TUCAMRET.TUCAMRET_SUCCESS == waitForFrameResult)
                {
                    // Change drawing area
                    if (drawingBox.Width != m_frame.usWidth || drawingBox.Height != m_frame.usHeight || m_clientWinWidth != clientWinWidth || m_clientWinHeight != clientWinHeight)
                    {
                        clientWinWidth = drawingBox.Width;
                        clientWinHeight = drawingBox.Height;

                        float scaleX = clientWinWidth * 1.0f / m_frame.usWidth;
                        float scaleY = clientWinHeight * 1.0f / m_frame.usHeight;
                        float scale = scaleX > scaleY ? scaleY : scaleX;
                        scale = (float)((int)(scale * 100) / 100.0f);

                        if (scale < 1)
                        {
                            drawingWidth = (int)(scale * m_frame.usWidth);
                            drawingHeight = (int)(scale * m_frame.usHeight);
                        }
                        else
                        {
                            drawingWidth = m_frame.usWidth;
                            drawingHeight = m_frame.usHeight;
                        }

                        drawingWidth = (drawingWidth >> 2) << 2;
                        drawingHeight = (drawingHeight >> 2) << 2;

                        drawingOffsetX = (clientWinWidth - drawingWidth) / 2;
                        drawingOffsetY = (clientWinHeight - drawingHeight) / 2;
                    }

                    // Drawing image
                    if (IntPtr.Zero != m_frame.pBuffer)
                    {
                        m_drawing.pFrame = Marshal.AllocHGlobal(Marshal.SizeOf(m_frame));
                        Marshal.StructureToPtr(m_frame, m_drawing.pFrame, true);

                        m_drawing.nDstX = drawingOffsetX;
                        m_drawing.nDstY = drawingOffsetY;
                        m_drawing.nDstWidth = drawingWidth;
                        m_drawing.nDstHeight = drawingHeight;

                        m_drawing.nSrcX = 0;
                        m_drawing.nSrcY = 0;
                        m_drawing.nSrcWidth = m_frame.usWidth;
                        m_drawing.nSrcHeight = m_frame.usHeight;

                        var drawFrameResult = TUCamAPI.TUCAM_Draw_Frame(hIdxTUCam, ref m_drawing);
                        if (TUCAMRET.TUCAMRET_SUCCESS != drawFrameResult)
                        {
                            Console.WriteLine("TUCAM_Draw_Frame失败：{0}", drawFrameResult);
                        }
                    }

                    // Saving video
                    /* if (m_isRecording)
                     {
                         TUCamAPI.TUCAM_Rec_AppendFrame(hIdxTUCam, ref m_frame);
                     }*/

                    // Saving image
                    if (m_isSaving || m_isTrigger)
                    {
                        // string dir = m_filePath + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\" + currentFileBatchNum;
                       // CurrentBatchDir = dir;
                        string dir = CurrentBatchDir;
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        string timestamp = DateTime.Now.ToString("HHmmss");
                        //string fileName = m_filePath + "\\" + timestamp + "_" + m_imageName + "_" + m_captureTimes + "_" + m_savedFramesCnt++;
                        string fileName = dir + "\\" + timestamp + "_" + m_captureTimes;

                        bool isSucceed = false;

                        do
                        {
                            int fileFormat = m_savedFormat;
                            TUCAM_FILE_SAVE fileSave;

                            fileSave.pstrSavePath = Marshal.StringToHGlobalAnsi(fileName);

                            // struct to IntPtr
                            fileSave.pFrame = Marshal.AllocHGlobal(Marshal.SizeOf(m_frame));
                            Marshal.StructureToPtr(m_frame, fileSave.pFrame, true);

                            // Format RAW
                            if (0 != (fileFormat & (int)TUIMG_FORMATS.TUFMT_RAW))
                            {
                                fileFormat &= ~(int)TUIMG_FORMATS.TUFMT_RAW;
                            }

                            if (0 != fileFormat)
                            {
                                fileSave.nSaveFmt = fileFormat;

                                // Save other format data(TIFF/BMP/PNG/JPEG)
                                var saveImageResult = TUCamAPI.TUCAM_File_SaveImage(hIdxTUCam, fileSave);
                                if (TUCAMRET.TUCAMRET_SUCCESS != saveImageResult)
                                {
                                    Console.WriteLine("TUCAM_File_SaveImage失败：{0}", saveImageResult);
                                    break;
                                }
                            }

                            /*if (0 != (m_savedFormat & (int)TUIMG_FORMATS.TUFMT_RAW))
                            {
                                fileSave.nSaveFmt = (int)TUIMG_FORMATS.TUFMT_RAW;

                                // Get RAW data
                                m_frame.ucFormatGet = (int)TUFRM_FORMATS.TUFRM_FMT_RAW;
                                if (TUCAMRET.TUCAMRET_SUCCESS != TUCamAPI.TUCAM_Buf_CopyFrame(hIdxTUCam, ref m_frame))
                                {
                                    break;
                                }

                                // Save RAW data
                                if (TUCAMRET.TUCAMRET_SUCCESS != TUCamAPI.TUCAM_File_SaveImage(hIdxTUCam, fileSave))
                                {
                                    break;
                                }
                            }*/
                            /*BaiDuOcr baiDuOcr = new BaiDuOcr();
                            BaiduReturn.Text=baiDuOcr.GeneralBasicDemo(fileName+".jpg");
                            Client client=AlibabaOCR.CreateClient();
                            Stream bodySyream = AlibabaCloud.DarabonbaStream.StreamUtil.ReadFromFilePath(fileName + ".jpg");
                            AlibabaCloud.SDK.Ocr_api20210707.Models.RecognizeAdvancedRequest recognizeAdvancedRequest = new AlibabaCloud.SDK.Ocr_api20210707.Models.RecognizeAdvancedRequest
                            {
                                Body = bodySyream,
                                OutputFigure = true,
                                Row = true,
                                NeedSortPage = true,
                                NeedRotate = true,
                                OutputCharInfo = true,
                            };
                            AlibabaCloud.SDK.Ocr_api20210707.Models.RecognizeAdvancedResponse resp = client.RecognizeAdvanced(recognizeAdvancedRequest);
                            JObject jo = JObject.Parse(AlibabaCloud.TeaUtil.Common.ToJSONString(resp));
                            JObject dataJo=  JObject.Parse(jo.GetValue("Body")["Data"].ToString());
                            AlibabaCloud.TeaConsole.Client.Log(jo.GetValue("Body")["Data"].ToString());
                            //aireturn.Text = AlibabaCloud.TeaUtil.Common.ToJSONString(dataJo.GetValue("content"));
                            aireturn.Text = dataJo.GetValue("content").ToString();
                            AlibabaCloud.TeaConsole.Client.Log(AlibabaCloud.TeaUtil.Common.ToJSONString(resp));
                            TencentOCR tencentOCR = new TencentOCR();
                            TencentReturn.Text=tencentOCR.GetTencentOCR(fileName + ".jpg");*/
                            if (!string.IsNullOrEmpty(fileName))
                            {
                                string fileFullPath = fileName + ".jpg";
                                Console.WriteLine("抓拍到图片：" + fileFullPath);
                                this.captureImageDelegate.Invoke(fileFullPath);
                                captureing = false;
                            }
                            isSucceed = true;

                        } while (false);

                        if (isSucceed)
                        {
                            m_savedSucceedCnt++;

                            // capture finished
                            if (m_savedSucceedCnt >= m_totalFrames)
                            {
                                m_isSaving = false;

                                /*FinishedCaptureInvoke finished = new FinishedCaptureInvoke(FinishedCapture);
                                form.BeginInvoke(finished, new object[] { m_savedSucceedCnt });*/
                            }
                        }
                    }
                }
                else
                {
                    Console.WriteLine("TUCAM_Buf_WaitForFrame失败，{0}", waitForFrameResult);
                }
            }
        }

        private void StartWaitForFrame(TUCAM_OPEN opCam)
        {
            if (m_isWaiting)
                return;

            if (m_opCamList.Count > 0)
            {
                m_isWaiting = true;
                m_waitingThread = new Thread(new ThreadStart(WaitForFrameThreadEntity));

                m_frame.pBuffer = IntPtr.Zero;
                m_frame.ucFormatGet = (byte)TUFRM_FORMATS.TUFRM_FMT_USUAl;
                m_frame.uiRsdSize = 1;

                TUCamAPI.TUCAM_Buf_Alloc(opCam.hIdxTUCam, ref m_frame);                           // Alloc buffer after set resolution or set ROI attribute                                           
                TUCamAPI.TUCAM_Cap_Start(opCam.hIdxTUCam, (uint)m_triggerAttr.nTgrMode);          // Start capture
                Console.WriteLine("相机开始取帧");
                m_waitingThread.Start();
            }
        }
        protected void StopWaitForFrame(TUCAM_OPEN opCam)
        {
            if (!m_isWaiting)
                return;

            if (m_opCamList.Count > 0)
            {
                try
                {
                    m_isSaving = false;
                    m_isWaiting = false;
                    m_drawingFramesCnt = 0;
                    m_startTime = new TimeSpan(DateTime.Now.Ticks);

                    TUCamAPI.TUCAM_Buf_AbortWait(opCam.hIdxTUCam);
                    m_waitingThread.Join();
                    m_waitingThread.Abort();

                    TUCamAPI.TUCAM_Cap_Stop(opCam.hIdxTUCam);                  // Stop capture   
                    TUCamAPI.TUCAM_Buf_Release(opCam.hIdxTUCam);               // Release alloc buffer after stop capture and quit drawing thread
                    Console.WriteLine("相机停止取帧");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }

        private void InitControlRange(TUCAM_OPEN opCam)
        {
            if (IntPtr.Zero == opCam.hIdxTUCam)
                return;

            //图像水平翻转
            TUCamAPI.TUCAM_Capa_SetValue(m_opCamList[m_indexCam].hIdxTUCam, (int)TUCAM_IDCAPA.TUIDC_HORIZONTAL, 1);
            //图像垂直翻转
            TUCamAPI.TUCAM_Capa_SetValue(m_opCamList[m_indexCam].hIdxTUCam, (int)TUCAM_IDCAPA.TUIDC_VERTICAL, 1);

            //曝光
            TUCamAPI.TUCAM_Capa_SetValue(m_opCamList[m_indexCam].hIdxTUCam, (int)TUCAM_IDCAPA.TUIDC_ATEXPOSURE, 0);//关闭自动曝光
            TUCamAPI.TUCAM_Prop_SetValue(m_opCamList[m_indexCam].hIdxTUCam, (int)TUCAM_IDPROP.TUIDP_EXPOSURETM, (double)(Config.CAMERA_EXPOSURE / 1000.0f), 0);//曝光值

        }


        /// <summary>
        /// 开启心跳
        /// </summary>监测
        public void WatchHeartBeat()
        {
            heartBeatEnabled = true;
            heartBeatTimer.Enabled = true;
            heartBeatTimer.Start();
        }

        public void UnWatchHeartBeat()
        {
            heartBeatEnabled = false;
            heartBeatTimer.Stop();
            heartBeatTimer.Enabled = false;
        }

        /// <summary>
        /// 相机心跳监测
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void OnTimerHeartBeat(object source, System.Timers.ElapsedEventArgs e)
        {
            if (!heartBeatEnabled) return;
            var isOK = false;
            if (m_opCamList.Count > 0)
            {
                double paramValue = 0;
                isOK = (TUCAMRET.TUCAMRET_SUCCESS == TUCamAPI.TUCAM_Prop_GetValue(m_opCamList[m_indexCam].hIdxTUCam, (int)TUCAM_IDPROP.TUIDP_GLOBALGAIN, ref paramValue, 0));
            
            }
            Console.WriteLine("相机心跳监测:"+ isOK);
            if (heartBeatDelegate != null) {
                heartBeatDelegate.Invoke(isOK);
            }
        }

        /// <summary>
        /// 开始拍照（捕获）
        /// </summary>
        public void StartCapture()
        {
            m_imageName = "TS";//文件名字
            m_totalFrames = 1;//捕获帧数
            if (!Directory.Exists(m_filePath))
            {
                Directory.CreateDirectory(m_filePath, null);
            }

            Console.WriteLine("开始抓拍");
            SoundHelper.PlayAudio("capture.wav");
            m_captureTimes++;
            m_savedFramesCnt = 1;
            m_savedSucceedCnt = 0;
            m_isSaving = true;
        }

        /// <summary>
        /// ListForm清除了数据，就需要增加新文件夹
        /// </summary>
        public void IncreaseCurrentFileBatchNum()
        {
            currentFileBatchNum++;
            string dir = m_filePath + "\\" + DateTime.Now.ToString("yyyy-MM-dd");
            string batchDir = dir + '\\' + currentFileBatchNum;
            if (!Directory.Exists(batchDir))
            {
                Directory.CreateDirectory(batchDir);
            }
        }

        /// <summary>
        /// 仅采样+拉直，不进行OCR识别
        /// </summary>
        private bool isSample = false;

        public void SetSample(bool isSample)
        {
            this.isSample = isSample;
        }
    }
}
